import { defineStore } from 'pinia'
import { ref, watch } from 'vue'
import Plyr from 'plyr'
import { baseUrl } from "@/configs/config";
import {useAuthStore} from "@/stores";
import { interactionMusicService } from '@/apis/music'
import _ from "lodash";

export enum PlayStatus{
    playing,
    stoped,
    pause,
    error,
    ready
}

export enum PlayMode{
    Single,
    Order,
    Shuffle,
    Normal
}

export const useAudioPlayerStore = defineStore('audioplayerStore', () => {
    const inited = ref<boolean>(false)
    const audioRef = ref<HTMLAudioElement | null>(null)
    const status = ref<PlayStatus>(PlayStatus.stoped)
    const musicPlayer = ref<Plyr | null>(null)
    const playMode = ref<PlayMode>(PlayMode.Normal)
    const playingSong = ref<song_info | null>(null)
    const currentTime = ref<number>(0)
    const songTime = ref<number>(0)
    const songLyric = ref<string>('')
    const autoPlay = ref<boolean>(false)
    const voice = ref<number>(61)
    const muted = ref<boolean>(false)
    const authStore = useAuthStore()
    const source = ref<MediaElementAudioSourceNode | null>(null)
    //let source = null
    //const audioContext = new (window.AudioContext || window.webkitAudioContext)()
    const audioContext = new window.AudioContext()
    const analyser = audioContext.createAnalyser()
    analyser.fftSize = 2048;

    const songList = ref<song_info[]>([])
    const addSong = (newSong: song_info ) => {
        const find = findInList(newSong.id)

        if(!find)
        {
            songList.value = [...songList.value,newSong]
        }

    }
    const removeSong = (s: song_info) => {
        songList.value = songList.value.filter(item => item.id !== s.id)
    }

    const findNextSong = (song: song_info, flag:boolean = false) => {
        const index = _.indexOf(songList.value, song)
        if(index < songList.value.length - 1)
        {
            return songList.value[index + 1]
        }
        else
        {
            if(flag)
            {
                return _.first(songList.value)
            }
            else {
                return undefined
            }

        }
    }

    const findPrevSong = (song: song_info, flag:boolean = false) => {
        const index = _.indexOf(songList.value, song)
        if(index >= 1)
        {
            return songList.value[index - 1]
        }
        else
        {
            if(flag)
            {
                return _.last(songList.value)
            }
            else {
                return undefined
            }

        }
    }

    watch(voice,(newVoice)=>{
        if(musicPlayer.value !== null)
        {
            musicPlayer.value.volume = newVoice / 100
        }
    })

    const getRandomSong = () =>{
        const index = _.random(0,songList.value.length - 1,false)
        return songList.value[index]
    }

    const findInList = (id: string) => {
        if(songList.value.length > 0)
        {
            const find  = songList.value.find(item => item.id === id)
            return find !== undefined;

        }
        return false
    }

    const exist = (id:string) => {
        return findInList(id)
    }

    const setSongList = (ss: song_info[]) => {
        songList.value = ss
    }
    const clearSongs = () => {
        songList.value = []
    }

    const setMuted = (flag: boolean) => {
        muted.value = flag
    }

    watch(muted,(newValue)=>{
        if(musicPlayer.value !== null)
        {
            musicPlayer.value.muted = newValue
        }
    })

    const initPlayer = (element : HTMLAudioElement,controls: string[] | string) => {
        audioRef.value = element
        musicPlayer.value = new Plyr(element,{controls: controls,volume: voice.value / 100, muted: muted.value})
        inited.value = true
        status.value = PlayStatus.ready
        musicPlayer.value.on("ready", () => {
            if(autoPlay.value)
            {
                play()
            }
        })
        musicPlayer.value.volume = voice.value / 100

        musicPlayer.value.on("timeupdate", () => {
            currentTime.value = musicPlayer.value!.currentTime
        })

        musicPlayer.value.on("ended", () => {
             onPlayEnd()
        })

        musicPlayer.value.on("playing", () => {
            status.value = PlayStatus.playing
        })

        musicPlayer.value.on("pause", () => {
            //status.value = PlayStatus.pause
        })

        musicPlayer.value.on("progress", () => {

        })


        if(playingSong.value !== null)
        {
            musicPlayer.value.source =  {
                type: 'audio',
                title: playingSong.value?.title,
                sources: [
                    {
                        src: getSongUrl(),
                    }
                ],
            };
        }

        source.value = audioContext.createMediaElementSource(musicPlayer.value.media)
        source.value.connect(analyser)
        source.value.connect(audioContext.destination)
    }

    const addPlayedCount = async (id: string) => {
        await interactionMusicService(id)
    }
    const setPlayingSong = (song: song_info, Play:boolean = false) => {
        if(inited.value === true)
        {
            autoPlay.value = Play
            if(playingSong.value === null || song.id !== playingSong!.value.id)
            {
                playingSong.value = song
                songTime.value = song.length
                addPlayedCount(song.id)
                addSong(song)
            }
            else if(song.id === playingSong!.value.id)
            {
                setPlayingTime(0)
                if(autoPlay.value === true && status.value !== PlayStatus.playing)
                {
                    play()
                }
            }
        }
        else {
            console.log("not init")
        }
    }

    const setPlayingTime = (time: number) => {
        if(SongIsReady())
        {
            musicPlayer.value!.currentTime = time
        }
    }


    const setNextPlay = (song: song_info)=>{
        playingSong.value = song
        songTime.value = song.length
        play()
    }

    const setNextPlayMode = () => {

    }


    const NextPlay = () => {
        const song = findNextSong(<song_info>playingSong.value)
        if(song){
            setNextPlay(song)
        }
    }

    const PrevPlay = () => {
        const song = findPrevSong(<song_info>playingSong.value)
        if(song){
            setNextPlay(song)
        }
    }

    const NextPlayOrder = () => {
        const song = findNextSong(<song_info>playingSong.value,true)
        if(song){
            setNextPlay(song)
        }
    }

    const NextPrevOrder = () => {
        const song = findPrevSong(<song_info>playingSong.value,true)
        if(song){
            setNextPlay(song)
        }
    }
    const shufflePlay = () => {
        const song = getRandomSong()
        if(song){
            setNextPlay(song)
        }
    }

    const onEndNext = () => {
        switch (playMode.value)
        {
            case PlayMode.Normal:
                NextPlay()
                break;
            case PlayMode.Order:
                NextPlayOrder()
                break;
            case PlayMode.Shuffle:
                shufflePlay()
                break;
        }
    }

    const Next = () => {
        switch (playMode.value)
        {
            case PlayMode.Normal:
                NextPlayOrder()
                break;
            case PlayMode.Order:
                NextPlayOrder()
                break;
            case PlayMode.Shuffle:
                shufflePlay()
                break;
            case PlayMode.Single:
                NextPlayOrder()
                break;
        }

    }

    const onEnd = () => {
        if(playMode.value === PlayMode.Single)
        {
            setPlayingTime(0)
            play()
        }
        else {
            onEndNext()
        }
    }

    const setLike = (songId: string, liked:boolean) => {
        //正在播放的如何是，则修改
        if(playingSong.value!== null && playingSong.value.id === songId)
        {
            playingSong.value.liked = liked
        }

        //播放列表
        const tmpList = songList.value
        tmpList.map(item => {
            if(item.id === songId)
            {
                item.liked = liked
            }
            
        })
        songList.value = tmpList
    }

    const Prev = () => {
        switch (playMode.value)
        {

            case PlayMode.Normal:
                PrevPlay()
                break;
            case PlayMode.Order:
                NextPrevOrder()
                break;
            case PlayMode.Shuffle:
                shufflePlay()
                break;
            case PlayMode.Single:
                PrevPlay()
                break;
        }

    }

    const onPlayEnd = async () => {
        status.value = PlayStatus.stoped
        setTimeout(()=>{
            onEnd()
        },1000)
        //onEnd()

    }

    const setPlayMode = (mode: PlayMode) => {
        playMode.value = mode
    }

    watch(playingSong,()=>{
        if(playingSong.value !== null && musicPlayer.value)
        {
            musicPlayer.value.source =  {
                type: 'audio',
                title: playingSong.value?.title,
                sources: [
                    {
                        src: getSongUrl(),
                    }
                ],
            }

            if(audioRef.value !== null )
            {
                if(source.value)
                {
                    source.value.disconnect()
                }
                source.value = audioContext.createMediaElementSource(musicPlayer.value.media)
                source.value.connect(analyser)
                source.value.connect(audioContext.destination)
            }

        }

    })


    const getSongUrl = ():string => {
        if(playingSong.value !== null) {
            return baseUrl + '/play/' + playingSong.value.id + "/?t=" + authStore.audioToken
        }
        else {
            return ''
        }
    }

    const play = () => {
        if(SongIsReady())
        {
            if(playingSong.value !== null)
            {
                document.title = `${playingSong.value?.title} ♫`
                addSong(playingSong.value)
            }
            musicPlayer.value?.play()

        }
    }

    const SongIsReady = () : boolean => {
        return playerIsEnable() && playingSong.value !== null;
    }

    const stop = () => {
        if(playerIsEnable())
        {
            musicPlayer.value?.stop()
        }
    }

    const playerIsEnable = () =>{
        return inited.value === true && playingSong.value !== null;
    }

    const pause = () => {
        if(playerIsEnable())
        {
            musicPlayer.value?.pause()
            status.value = PlayStatus.pause
        }
    }

    const changePlayMode = (mode: PlayMode) => {
        playMode.value = mode
    }

    return {
        initPlayer,
        play,
        playMode,
        status,
        inited,
        audioRef,
        analyser,
        audioContext,
        source,
        musicPlayer,
        setPlayingSong,
        stop,
        pause,
        currentTime,
        songTime,
        playingSong,
        songLyric,
        changePlayMode,
        getSongUrl,
        setPlayingTime,
        setPlayMode,
        setNextPlayMode,
        onPlayEnd,
        setSongList,
        addSong,
        exist,
        clearSongs,
        Next,
        Prev,
        songList,
        removeSong,
        voice,
        muted,
        setMuted,
        setLike
    }
}, {
    persist: {
        paths:["playMode","playingSong","songTime","voice","muted"]
    }
})
